package com.xiaopangzi.websocket.directive.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * 描述: WebSocket连接服务
 * 由Javax包提供支持
 *
 * @author : sujinchen
 * @date : 2020/9/21
 */
@ServerEndpoint("/ws")
@Service
public class MyJavaxWebSocketImpl {
    private Logger log = LoggerFactory.getLogger(MyJavaxWebSocketImpl.class);

    /**
     * 记录当前在线连接数，设计为线程安全的
     */
    private static int onlineCount = 0;

    /**
     * concurrent包是线程安全的Set，用来存放每个客户端对应的WebSockets
     * 每个客户端打开时，都会为其创建一个MyJavaxWebSocketImpl对象，
     */
    private static CopyOnWriteArraySet<MyJavaxWebSocketImpl> webSockets = new CopyOnWriteArraySet<MyJavaxWebSocketImpl>();

    /**
     * 当前正在使用的Session
     */
    private Session currentSession;


    /**
     * 建立连接，将在线客户端以sessionId保存
     *
     * @param session 会话
     */

    @OnOpen
    public void onOpen(Session session) {
        String id = session.getId();
        log.info("有新的客户端连接了: {}", id);
        this.currentSession = session;
        webSockets.add(this);
        sendOne("有新的连接加入",false);
    }

    /**
     * 关闭连接，移除在线客户端
     *
     * @param session
     */
    @OnClose
    public void onClose(Session session) {
        log.info("断开连接: {}", session.getId());
        webSockets.remove(this);
    }

    /**
     * 发生错误
     *
     * @param throwable 错误内容
     */
    @OnError
    public void onError(Throwable throwable,Session session) {
        log.error("有客户端连接发生错误！错误连接：{}，错误内容：{}", this.currentSession, throwable.getMessage());
        throwable.printStackTrace();
    }

    /**
     * 接收到消息，可对消息进行处理。
     *
     * @param message
     */
    @OnMessage
    public void onMessage(String message) {
        log.info("服务端接收到客户端的消息为：{}", message);
        if (message.equals("a")) {
            message = String.format("hellow {}%s", message);
            sendAll(message, false);
        } else {
            sendAll(message,false);
        }
    }


    /**
     * 服务器群发通知客户端
     * @param mesage
     */
    public void sendAll(String mesage,boolean async) {
            if (async) {
                for (MyJavaxWebSocketImpl websocket:webSockets
                     ) {
                    websocket.currentSession.getAsyncRemote().sendText(mesage);
                }
            } else {
                for (MyJavaxWebSocketImpl websocket:webSockets
                ) {
                    try {
                        websocket.currentSession.getBasicRemote().sendText(mesage);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }

    }

    /**
     * 服务器单独通知客户端
     * @param message
     */
    public void sendOne( String message,boolean async) {
            if (async) {
                this.currentSession.getAsyncRemote().sendText(message);

            } else {
                try {
                    this.currentSession.getBasicRemote().sendText(message);
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
    }

}
